﻿// Copyright (c) 2017 GlassGrass

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;
using UniRx;



namespace GlassGrass.Unity.GuiFramework
	{
	/// <summary> On/off toggle button or checkbox. </summary>
	public class Toggle : GuiElement, IBindable<bool>
		{
		#region events

		/// <summary> Be fired when this Checked state was changed. </summary>
		public IObservable<bool> CheckedChanged => _checkedChanged.DistinctUntilChanged();
		private readonly Subject<bool> _checkedChanged = new Subject<bool>();

		#endregion



		#region fields and properties

		/// <summary> Checked state. </summary>
		public bool Checked
			{
			get => _checked;
			set
				{
				_checked = value;
				_checkedChanged.OnNext(value);
				}
			}
		private bool _checked = false;

		#endregion



		/// <summary> Create Toggle instance. </summary>
		/// <param name="config"> [Non-Nullable] </param>
		/// <exception cref="System.ArgumentNullException"></exception>
		public Toggle(GuiConfig config) : base(config)
			{
			}



		/// <summary> Define what to choose style for this from skin. </summary>
		/// <param name="skin"></param>
		/// <returns></returns>
		protected override GUIStyle ChooseStyle(GUISkin skin)
			=> GUI.skin.toggle;



		/// <summary> Define how to layout manually itself on rendering frame. </summary>
		/// <param name="parentSkin"></param>
		public override void LayoutManual(GUISkin parentSkin)
			{
			Checked = GUI.Toggle( Rect, Checked, Content, SelectValidStyle( parentSkin ) );
			}



		/// <summary> Define how to layout automatically itself on rendering frame.  </summary>
		/// <param name="parentSkin"></param>
		public override void LayoutAuto(GUISkin parentSkin)
			{
			Checked = GUILayout.Toggle( Checked, Content, SelectValidStyle(parentSkin), LayoutOptions);
			}



		/// <summary> Get 'Checked' property binder. </summary>
		/// <returns></returns>
		public IBindable<bool> AsCheckedBindable() => this;



		/// <summary> Begin 'Checked' property binding. </summary>
		/// <typeparam name="TValue"> Type of model property. </typeparam>
		/// <param name="modelObj"> Model object instance. </param>
		/// <param name="propertyName"> Model object property for binding. </param>
		/// <param name="converter"> Value converter. </param>
		/// <returns></returns>
		Binding<TValue, bool> IBindable<bool>.BeginBinding<TValue>(object modelObj, string propertyName, IValueConverter<TValue, bool> converter)
			=> GuiBindingFactory.BeginBinding( modelObj, propertyName, this, nameof( Checked ), converter, CheckedChanged);

		}
	}
